package service

import (
	"douyin/controller/api/response"
	"douyin/dao"
	"douyin/errno"
	"douyin/model"
	"douyin/utils"
	"fmt"
	"log"
	"time"

	"github.com/garyburd/redigo/redis"
)

var (
	err    error
	status = response.OK
)

// Follow 关注 增加关注对象和对象的粉丝
func Follow(toUserId int64, userId int64) (response.Status, error) {
	//包装Redis的key
	followeeKey := utils.GetFolloweeKey(userId)
	followerKey := utils.GetFollowerKey(toUserId)

	//取redis连接
	conn := dao.GetRedisConn()
	nowMillSecond := time.Now().UnixMilli()
	//开启事务，存入Redis，数据类型采用ZSet，以时间戳作为score，方便后续关注/粉丝列表可以以关注时间排序
	err = conn.Send("MULTI")
	if err != nil {
		status = handleError(errno.ErrMulti)
		return status, err
	}
	err = dao.FollowDAO.AddFollowee(conn, followeeKey, nowMillSecond, toUserId, err)
	if err != nil {
		log.Println("关注添加失败:", err)
		return handleError(errno.ErrFollowFail), err
	}
	err = dao.FollowDAO.AddFollower(conn, followerKey, nowMillSecond, userId, err)
	if err != nil {
		log.Println("粉丝添加失败:", err)
		return handleError(errno.ErrFollowFail), err
	}
	_, err = conn.Do("EXEC")
	if err != nil {
		return handleError(errno.ErrExec), err
	}
	//redis关闭连接
	defer handleConnError(conn, status)
	return status, err
}

// Unfollow 取关 删除关注对象和对象的粉丝
func Unfollow(toUserId int64, userId int64) (response.Status, error) {
	//包装Redis的key
	followeeKey := utils.GetFolloweeKey(userId)
	followerKey := utils.GetFollowerKey(toUserId)
	status = response.OK
	//取redis连接
	conn := dao.GetRedisConn()
	//开启事务，在Redis删除
	err = conn.Send("MULTI")
	if err != nil {
		status = handleError(errno.ErrMulti)
		return status, err
	}
	err = dao.FollowDAO.RemFollowee(conn, followeeKey, toUserId, err)
	if err != nil {
		log.Println("关注删除失败:", err)
		status = handleError(errno.ErrFollowFail)
		return status, err
	}
	err = dao.FollowDAO.RemFollower(conn, followerKey, userId, err)
	if err != nil {
		log.Println("粉丝删除失败:", err)
		status = handleError(errno.ErrFollowFail)
		return status, err
	}
	_, err = conn.Do("EXEC")
	if err != nil {
		status = handleError(errno.ErrExec)
		return status, err
	}
	//redis关闭连接
	defer handleConnError(conn, status)
	return status, err
}

// QueryFolloweeCount 查询关注对象的数量
func QueryFolloweeCount(userId int64) (int, response.Status, error) {
	//取关注列表key
	followeeKey := utils.GetFolloweeKey(userId)
	//取redis连接
	conn := dao.GetRedisConn()
	status = response.OK
	count, err2 := redis.Int(conn.Do("ZCOUNT", followeeKey, 0, 9223372036854775807)) //int64最大值：9223372036854775807（时间戳范围0-最大值）
	fmt.Print("ZCOUNT", count)
	if err2 != nil {
		return -1, handleError(errno.ErrQueryFolloweeCount), err2
	}
	//redis关闭连接
	defer handleConnError(conn, status)
	return count, status, err
}

// QueryFollowerCount 查询对象的粉丝数量
func QueryFollowerCount(toUserId int64) (int, response.Status, error) {
	//取粉丝列表key
	followerKey := utils.GetFollowerKey(toUserId)
	//取redis连接
	conn := dao.GetRedisConn()
	status = response.OK
	count, err2 := redis.Int(conn.Do("ZCOUNT", followerKey, 0, 9223372036854775807)) //int64最大值：9223372036854775807（时间戳范围0-最大值）
	fmt.Print("ZCOUNT", count)
	if err2 != nil {
		return -1, handleError(errno.ErrQueryFollowerCount), err2
	}
	//redis关闭连接
	defer handleConnError(conn, status)
	return count, status, err
}

// IsFollow 查询当前用户是否关注该对象
func IsFollow(userId int64, toUserId int64) (bool, error) {
	//取关注列表key
	followeeKey := utils.GetFolloweeKey(userId)
	//取redis连接
	conn := dao.GetRedisConn()
	//判断redis查score的错误
	_, err := redis.Int(conn.Do("ZSCORE", followeeKey, toUserId))
	if err != nil {
		return false, nil
	}
	//redis关闭连接
	defer func(conn redis.Conn) {
		err := conn.Close()
		if err != nil {
			log.Println("redis连接关闭失败：", err)
		}
	}(conn)
	return true, err
}

// 处理错误
func handleError(errorType *errno.Errno) response.Status {
	return response.Status{Code: errorType.Code, Message: errorType.Message}
}

// 处理redis连接关闭错误
func handleConnError(conn redis.Conn, status response.Status) {
	err = conn.Close()
	if err != nil {
		log.Println("redis连接关闭失败：", err)
		status = handleError(errno.ErrRedisClose)
	}
}

// QueryFollow 查询某用户关注的人
func QueryFollow(userId int64) (response.FolloweeList, error) {
	//取关注列表key
	followeeKey := utils.GetFolloweeKey(userId)
	//取redis连接
	conn := dao.GetRedisConn()
	r, _ := redis.Ints(conn.Do("ZRANGE", followeeKey, 0, -1))
	if len(r) == 0 {
		log.Println("暂无关注")
		return response.FolloweeList{Status: response.OK}, err
	}
	var userList []model.UserAPI
	for _, u := range r {
		name, err := getUserName(int64(u))
		if err != nil {
			return response.FolloweeList{
				Status: handleError(errno.ErrQueryUserNameFail),
			}, err
		}
		followCount, status, err := QueryFolloweeCount(int64(u))
		if err != nil {
			return response.FolloweeList{Status: status}, err
		}
		followerCount, status, err := QueryFollowerCount(int64(u))
		if err != nil {
			return response.FolloweeList{Status: status}, err
		}
		isfollow, err := IsFollow(userId, int64(u)) //关注列表应该都是已关注，考虑直接用true
		if err != nil {
			return response.FolloweeList{Status: handleError(errno.ErrQueryIsFollow)}, err
		}
		userList = append(userList, model.UserAPI{
			ID:            int64(u),
			Name:          name,
			FollowCount:   int64(followCount),
			FollowerCount: int64(followerCount),
			IsFollow:      isfollow,
		})
	}

	defer func(conn redis.Conn) {
		err := conn.Close()
		if err != nil {
			log.Println("redis连接关闭失败：", err)
		}
	}(conn)
	return response.FolloweeList{
		Status:   response.OK,
		UserList: userList,
	}, err
}

// QueryFollowers 查询某用户的粉丝
func QueryFollowers(userId int64) (response.FollowerList, error) {
	//取关注列表key
	followerKey := utils.GetFollowerKey(userId)
	//取redis连接
	conn := dao.GetRedisConn()
	r, _ := redis.Ints(conn.Do("ZRANGE", followerKey, 0, -1))
	if len(r) == 0 {
		log.Println("暂无粉丝")
		return response.FollowerList{Status: response.OK}, err
	}
	var userList []model.UserAPI
	for _, u := range r {
		name, err := getUserName(int64(u))
		if err != nil {
			return response.FollowerList{
				Status: handleError(errno.ErrQueryUserNameFail),
			}, err
		}
		followCount, status, err := QueryFolloweeCount(int64(u))
		if err != nil {
			return response.FollowerList{Status: status}, err
		}
		followerCount, status, err := QueryFollowerCount(int64(u))
		if err != nil {
			return response.FollowerList{Status: status}, err
		}
		isfollow, err := IsFollow(userId, int64(u))
		if err != nil {
			return response.FollowerList{Status: handleError(errno.ErrQueryIsFollow)}, err
		}
		userList = append(userList, model.UserAPI{
			ID:            int64(u),
			Name:          name,
			FollowCount:   int64(followCount),
			FollowerCount: int64(followerCount),
			IsFollow:      isfollow,
		})
	}

	defer func(conn redis.Conn) {
		err := conn.Close()
		if err != nil {
			log.Println("redis连接关闭失败：", err)
		}
	}(conn)
	return response.FollowerList{
		Status:   response.OK,
		UserList: userList,
	}, err
}
